package com.xdcplus.web.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.xdcplus.exceptions.ResponseUtils;
import com.xdcplus.mdm.api.PmShiftPlanRemote;
import com.xdcplus.mdm.api.vo.PmShiftManageWithPlanVO;
import com.xdcplus.mom.constants.NumberConstant;
import com.xdcplus.mom.enums.ResponseEnum;
import com.xdcplus.exceptions.XdcWebException;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;

import cn.hutool.core.collection.CollectionUtil;

import com.xdcplus.mp.service.impl.BaseServiceImpl;
import com.xdcplus.web.common.pojo.vo.OpeJobTaskStaffingEO;
import com.xdcplus.web.mapper.OpeJobTaskStaffingMapper;
import com.xdcplus.web.common.pojo.entity.OpeJobTaskStaffing;
import com.xdcplus.web.common.pojo.dto.OpeJobTaskStaffingDTO;
import com.xdcplus.web.common.pojo.dto.OpeJobTaskStaffingFilterDTO;
import com.xdcplus.web.common.pojo.vo.OpeJobTaskStaffingVO;
import com.xdcplus.web.common.pojo.query.OpeJobTaskStaffingQuery;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageInfo;
import com.xdcplus.core.utils.BeanUtils;
import com.xdcplus.pager.vo.PageVO;
import com.xdcplus.mp.utils.PageableUtils;
import com.xdcplus.mp.utils.PropertyUtils;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.sql.Timestamp;

import com.xdcplus.web.service.OpeJobTaskStaffingService;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

/**
 * (OpeJobTaskStaffing)表服务实现类
 *
 * @author Zhecheng.Ren
 * @since 2024-10-29 14:59:20
 */
@Slf4j
@Service("opeJobTaskStaffingService")
public class OpeJobTaskStaffingServiceImpl extends BaseServiceImpl<OpeJobTaskStaffingMapper, OpeJobTaskStaffing, OpeJobTaskStaffing, OpeJobTaskStaffingVO> implements OpeJobTaskStaffingService {

    @Resource
    protected OpeJobTaskStaffingMapper opeJobTaskStaffingMapper;
    @Resource
    private PmShiftPlanRemote pmShiftPlanRemote;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean saveOpeJobTaskStaffing(OpeJobTaskStaffingDTO opeJobTaskStaffingDTO) {

        String toolCode = opeJobTaskStaffingDTO.getToolCode();
        String shiftCode = opeJobTaskStaffingDTO.getShiftCode();

        OpeJobTaskStaffing opeJobTaskStaffing = new OpeJobTaskStaffing();
        BeanUtil.copyProperties(opeJobTaskStaffingDTO, opeJobTaskStaffing);
        opeJobTaskStaffing.setCreatedTime(new Timestamp(DateUtil.current()));
        OpeJobTaskStaffing jobTaskStaffing = opeJobTaskStaffingMapper.queryByToolCodeAndShift(toolCode, shiftCode);
        if (ObjectUtil.isNotNull(jobTaskStaffing)) {
            throw new XdcWebException(ResponseEnum.ERROR, "该设备该班次人员已配置");
        }
        return this.save(opeJobTaskStaffing);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean updateOpeJobTaskStaffing(OpeJobTaskStaffingDTO opeJobTaskStaffingDTO) {

        OpeJobTaskStaffing opeJobTaskStaffing = this.getById(opeJobTaskStaffingDTO.getId());
        String toolCode = opeJobTaskStaffingDTO.getToolCode();
        String shiftCode = opeJobTaskStaffingDTO.getShiftCode();
        if (ObjectUtil.isNull(opeJobTaskStaffing)) {
            log.error("updateOpeJobTaskStaffing() The OpeJobTaskStaffing does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }
        OpeJobTaskStaffing jobTaskStaffing = opeJobTaskStaffingMapper.queryByToolCodeAndShiftNotId(toolCode, shiftCode, opeJobTaskStaffing.getId());
        if (ObjectUtil.isNotNull(jobTaskStaffing)) {
            throw new XdcWebException(ResponseEnum.ERROR, "该设备该班次人员已配置");
        }

        BeanUtil.copyProperties(opeJobTaskStaffingDTO, opeJobTaskStaffing);
        opeJobTaskStaffing.setUpdatedUser(opeJobTaskStaffingDTO.getUpdatedUser());
        opeJobTaskStaffing.setUpdatedTime(new Timestamp(DateUtil.current()));

        return this.updateById(opeJobTaskStaffing);
    }

    @Override
    public Boolean saveOrUpdateBatch(List<OpeJobTaskStaffing> opeJobTaskStaffingList) {

        opeJobTaskStaffingList.forEach(opeJobTaskStaffing -> {
            OpeJobTaskStaffing opeJobTaskStaffingParam = new OpeJobTaskStaffing();
            opeJobTaskStaffingParam.setId(opeJobTaskStaffing.getId());
            if (ObjectUtil.isNotNull(opeJobTaskStaffing.getId())) {
                opeJobTaskStaffing.setId(opeJobTaskStaffing.getId());
                opeJobTaskStaffing.setUpdatedTime(new Timestamp(DateUtil.current()));
                LambdaUpdateWrapper<OpeJobTaskStaffing> lambdaUpdate = Wrappers.lambdaUpdate();
                lambdaUpdate.eq(OpeJobTaskStaffing::getId, opeJobTaskStaffing.getId());
                update(opeJobTaskStaffing, lambdaUpdate);
            } else {
                opeJobTaskStaffing.setCreatedTime(new Timestamp(DateUtil.current()));
                save(opeJobTaskStaffing);
            }
        });
        return true;
    }

    @Override
    public Boolean saveOrUpdateBatchByDTOList(List<OpeJobTaskStaffingDTO> opeJobTaskStaffingDTOList) {

        List<OpeJobTaskStaffing> opeJobTaskStaffingList = BeanUtils.copyProperties(opeJobTaskStaffingDTOList, OpeJobTaskStaffing.class);
        return saveOrUpdateBatch(opeJobTaskStaffingList);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteOpeJobTaskStaffingLogical(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        OpeJobTaskStaffing opeJobTaskStaffing = this.getById(id);

        if (ObjectUtil.isNull(opeJobTaskStaffing)) {
            log.error("deleteOpeJobTaskStaffing() The OpeJobTaskStaffing does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }
        return this.removeById(id);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteOpeJobTaskStaffingByIds(String ids) {
        Assert.notNull(ids, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());
        List<String> idList = Arrays.asList(ids.split(","));
        if (CollectionUtil.isEmpty(idList)) {
            throw new XdcWebException(ResponseEnum.ERROR);
        }
        idList.forEach(id -> {
            OpeJobTaskStaffing opeJobTaskStaffing = this.getById(id);
            if (ObjectUtil.isNull(opeJobTaskStaffing)) {
                log.error("deleteOpeJobTaskStaffing() The OpeJobTaskStaffing does not exist or has been deleted");
                throw new XdcWebException(ResponseEnum.ERROR);
            }
        });

        return this.removeByIds(idList);
    }

    private List<OpeJobTaskStaffingVO> queryOpeJobTaskStaffingList(OpeJobTaskStaffingFilterDTO opeJobTaskStaffingFilterDTO) {
        OpeJobTaskStaffingQuery opeJobTaskStaffingQuery = BeanUtil.copyProperties(opeJobTaskStaffingFilterDTO, OpeJobTaskStaffingQuery.class);

        return opeJobTaskStaffingMapper.queryOpeJobTaskStaffing(opeJobTaskStaffingQuery);
    }

    @Override
    public List<OpeJobTaskStaffingVO> queryOpeJobTaskStaffingVOList(OpeJobTaskStaffingFilterDTO opeJobTaskStaffingFilterDTO) {
        return queryOpeJobTaskStaffingList(opeJobTaskStaffingFilterDTO);
    }

    @Override
    public PageVO<OpeJobTaskStaffingVO> queryOpeJobTaskStaffing(OpeJobTaskStaffingFilterDTO opeJobTaskStaffingFilterDTO) {
        PageVO<OpeJobTaskStaffingVO> pageVO = new PageVO<>();

        if (opeJobTaskStaffingFilterDTO.getCurrentPage() > NumberConstant.ZERO) {
            PageableUtils.basicPage(opeJobTaskStaffingFilterDTO.getCurrentPage(), opeJobTaskStaffingFilterDTO.getPageSize(),
                    opeJobTaskStaffingFilterDTO.getOrderType(), opeJobTaskStaffingFilterDTO.getOrderField());
        }

        List<OpeJobTaskStaffingVO> opeJobTaskStaffingList = queryOpeJobTaskStaffingList(opeJobTaskStaffingFilterDTO);

        PageInfo<OpeJobTaskStaffingVO> pageInfo = new PageInfo<>(opeJobTaskStaffingList);
        PropertyUtils.copyProperties(pageInfo, pageVO, opeJobTaskStaffingList);

        return pageVO;
    }

    @Override
    public OpeJobTaskStaffingVO queryOpeJobTaskStaffingById(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        return this.objectConversion(this.getById(id));
    }

    @Override
    public OpeJobTaskStaffingVO queryOpeJobTaskStaffingByToolCode(String toolCode) {
        LocalDateTime now = LocalDateTime.now();
        String format = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        PmShiftManageWithPlanVO response = ResponseUtils.getResponse(pmShiftPlanRemote.queryPmShiftPlanWithManage(format));
        OpeJobTaskStaffing opeJobTaskStaffing = opeJobTaskStaffingMapper.queryByToolCodeAndShift(toolCode, response.getShiftCode());
        if (ObjectUtil.isNotNull(opeJobTaskStaffing)) {
            return this.objectConversion(opeJobTaskStaffing);
        }
        return null;
    }

    @Override
    public void templateDownload(HttpServletResponse response) throws UnsupportedEncodingException {
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("人员配置", "UTF-8") + ".xlsx");
        response.setContentType("application/octet-stream");
        try (ServletOutputStream outputStream = response.getOutputStream()) {
            EasyExcel.write(outputStream, OpeJobTaskStaffingEO.class).sheet("人员配置").doWrite(new ArrayList<>());
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    @Override
    public void importData(MultipartFile file, String account) throws IOException {
        File tmp = File.createTempFile("tmp", file.getOriginalFilename());
        file.transferTo(tmp);
        List<OpeJobTaskStaffing> opeJobTaskStaffingList = new ArrayList<>();
        EasyExcel.read(tmp, OpeJobTaskStaffingEO.class, new AnalysisEventListener<OpeJobTaskStaffingEO>() {

            @Override
            public void invoke(OpeJobTaskStaffingEO opeJobTaskStaffingEO, AnalysisContext analysisContext) {
                OpeJobTaskStaffing opeJobTaskStaffing = BeanUtil.copyProperties(opeJobTaskStaffingEO, OpeJobTaskStaffing.class);
                opeJobTaskStaffing.setCreatedTime(new Timestamp(DateUtil.current()));
                opeJobTaskStaffing.setCreatedUser(account);
                opeJobTaskStaffingList.add(opeJobTaskStaffing);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                opeJobTaskStaffingList.forEach(opeJobTaskStaffing -> {
                    opeJobTaskStaffingMapper.deleteByToolCodeAndShiftCode(opeJobTaskStaffing.getToolCode(), opeJobTaskStaffing.getShiftCode());
                    opeJobTaskStaffingMapper.insert(opeJobTaskStaffing);
                });
                boolean delete = tmp.delete();
                if (!delete) {
                    log.error("删除文件失败");
                }
            }
        }).sheet().doRead();
    }

    @Override
    public void exportData(OpeJobTaskStaffingFilterDTO opeJobTaskStaffingFilterDTO, HttpServletResponse response) throws UnsupportedEncodingException {
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("人员配置", "UTF-8") + ".xlsx");
        response.setContentType("application/octet-stream");

        OpeJobTaskStaffingQuery opeJobTaskStaffingQuery = BeanUtils.copyProperties(opeJobTaskStaffingFilterDTO, OpeJobTaskStaffingQuery.class);
        List<OpeJobTaskStaffingVO> opeJobTaskStaffingVOS = opeJobTaskStaffingMapper.queryOpeJobTaskStaffing(opeJobTaskStaffingQuery);

        List<OpeJobTaskStaffingEO> opeJobTaskStaffingEos = BeanUtil.copyToList(opeJobTaskStaffingVOS, OpeJobTaskStaffingEO.class);

        try (ServletOutputStream outputStream = response.getOutputStream()) {
            EasyExcel.write(outputStream, OpeJobTaskStaffingEO.class).sheet("人员配置").doWrite(opeJobTaskStaffingEos);
        } catch (Exception e) {
            log.info("exportEarlyWarningFromExcel {}", e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }
}
